xend: Implement VBD.media_change
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 16 Oct 2009 08:04:53 +0000 (09:04 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 16 Oct 2009 08:04:53 +0000 (09:04 +0100)
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
tools/python/xen/xend/XendAPI.py
tools/python/xen/xend/XendDomainInfo.py

index a489db01b157b6cc26acbd44de9b82f8e7017d37..6c492d94b5b0382deb311163358f5ffe0bac7638 100644 (file)
@@ -1960,8 +1960,44 @@ class XendAPI(object):
 
         return xen_api_success(return_cfg)
 
-    def VBD_media_change(self, session, vbd_ref, vdi_ref):
-        return xen_api_error(XEND_ERROR_UNSUPPORTED)
+    def VBD_media_change(self, session, vbd_ref, new_vdi_ref):
+        xendom = XendDomain.instance()
+        xennode = XendNode.instance()
+
+        vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
+        if not vm:
+            return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
+        cur_vbd_struct = vm.get_dev_xenapi_config('vbd', vbd_ref)
+        if not cur_vbd_struct:
+            return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
+        if cur_vbd_struct['type'] != XEN_API_VBD_TYPE[0]:   # Not CD
+            return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
+        if cur_vbd_struct['mode'] != 'RO':   # Not read only
+            return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
+
+        new_vdi = xennode.get_vdi_by_uuid(new_vdi_ref)
+        if not new_vdi:
+            return xen_api_error(['HANDLE_INVALID', 'VDI', new_vdi_ref])
+        new_vdi_image = new_vdi.get_location()
+
+        valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
+                         self.Base_attr_ro + self.Base_attr_rw
+
+        new_vbd_struct = {}
+        for k in cur_vbd_struct.keys():
+            if k in valid_vbd_keys:
+                new_vbd_struct[k] = cur_vbd_struct[k]
+        new_vbd_struct['VDI'] = new_vdi_ref
+
+        try:
+            XendTask.log_progress(0, 100,
+                                  vm.change_vdi_of_vbd,
+                                  new_vbd_struct, new_vdi_image)
+        except XendError, e:
+            log.exception("Error in VBD_media_change")
+            return xen_api_error(['INTERNAL_ERROR', str(e)]) 
+
+        return xen_api_success_void()
 
     # class methods
     def VBD_create(self, session, vbd_struct):
index d4fd6bffb8dddac1b53a5b599e182f438d859d16..e0891b46f33581d836ab8571ff6b2dd53b3f0b6f 100644 (file)
@@ -3970,6 +3970,37 @@ class XendDomainInfo:
         return dscsi_uuid
 
 
+    def change_vdi_of_vbd(self, xenapi_vbd, vdi_image_path):
+        """Change current VDI with the new VDI.
+
+        @param xenapi_vbd: vbd struct from the Xen API
+        @param vdi_image_path: path of VDI
+        """
+        dev_uuid = xenapi_vbd['uuid']
+        if dev_uuid not in self.info['devices']:
+            raise XendError('Device does not exist')
+
+        # Convert xenapi to sxp
+        if vdi_image_path.startswith('tap'):
+            dev_class = 'tap'
+        else:
+            dev_class = 'vbd'
+        dev_sxp = [
+            dev_class,
+            ['uuid',  dev_uuid],
+            ['uname', vdi_image_path],
+            ['dev',   '%s:cdrom' % xenapi_vbd['device']],
+            ['mode',  'r'],
+            ['VDI',   xenapi_vbd['VDI']]
+        ]
+
+        if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING,
+                                XEN_API_VM_POWER_STATE_PAUSED):
+            self.device_configure(dev_sxp)
+        else:
+            self.info.device_update(dev_uuid, dev_sxp)
+
+
     def destroy_device_by_uuid(self, dev_type, dev_uuid):
         if dev_uuid not in self.info['devices']:
             raise XendError('Device does not exist')